home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / MORIA3.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  31KB  |  1,235 lines

  1. /* source/moria3.c: misc code, mainly to handle player commands
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #ifdef __TURBOC__
  10. #include    <stdio.h>
  11. #endif
  12.  
  13. #include "config.h"
  14. #include "constant.h"
  15. #include "types.h"
  16. #include "externs.h"
  17.  
  18. #ifdef USG
  19. #ifndef ATARIST_MWC
  20. #include <string.h>
  21. #endif
  22. #else
  23. #include <strings.h>
  24. #endif
  25.  
  26. #if defined(LINT_ARGS)
  27. static void hit_trap(int, int);
  28. static void carry(int, int, int);
  29. static int summon_object(int, int, int, int);
  30. #endif
  31.  
  32.  
  33. /* Player hit a trap.    (Chuckle)            -RAK-    */
  34. static void hit_trap(y, x)
  35. int y, x;
  36. {
  37.   int i, ty, tx, num, dam;
  38.   register cave_type *c_ptr;
  39.   register struct misc *p_ptr;
  40.   register inven_type *t_ptr;
  41.   bigvtype tmp;
  42.  
  43.   end_find();
  44.   change_trap(y, x);
  45.   c_ptr = &cave[y][x];
  46.   p_ptr = &py.misc;
  47.   t_ptr = &t_list[c_ptr->tptr];
  48.   dam = pdamroll(t_ptr->damage);
  49.   switch(t_ptr->subval)
  50.     {
  51.     case 1:  /* Open pit*/
  52.       msg_print("You fell into a pit!");
  53.       if (py.flags.ffall)
  54.     msg_print("You gently float down.");
  55.       else
  56.       {
  57.     objdes(tmp, t_ptr, TRUE);
  58.     take_hit(dam, tmp);
  59.       }
  60.       break;
  61.     case 2: /* Arrow trap*/
  62.       if (test_hit(125, 0, 0, p_ptr->pac+p_ptr->ptoac, CLA_MISC_HIT))
  63.     {
  64.       objdes(tmp, t_ptr, TRUE);
  65.       take_hit(dam, tmp);
  66.       msg_print("An arrow hits you.");
  67.     }
  68.       else
  69.     msg_print("An arrow barely misses you.");
  70.       break;
  71.     case 3: /* Covered pit*/
  72.       msg_print("You fell into a covered pit.");
  73.       if (py.flags.ffall)
  74.     msg_print("You gently float down.");
  75.       else
  76.       {
  77.     objdes(tmp, t_ptr, TRUE);
  78.     take_hit(dam, tmp);
  79.       }
  80.       place_trap(y, x, 0);
  81.       break;
  82.     case 4: /* Trap door*/
  83.       msg_print("You fell through a trap door!");
  84.       new_level_flag = TRUE;
  85.       dun_level++;
  86.       if (py.flags.ffall)
  87.     msg_print("You gently float down.");
  88.       else
  89.     {
  90.       objdes(tmp, t_ptr, TRUE);
  91.       take_hit(dam, tmp);
  92.     }
  93.       /* Force the messages to display before starting to generate the
  94.      next level.  */
  95.       msg_print (CNIL);
  96.       break;
  97.     case 5: /* Sleep gas*/
  98.       if (py.flags.paralysis == 0)
  99.     {
  100.       msg_print("A strange white mist surrounds you!");
  101.       if (py.flags.free_act)
  102.         msg_print("You are unaffected.");
  103.       else
  104.         {
  105.           msg_print("You fall asleep.");
  106.           py.flags.paralysis += randint(10) + 4;
  107.         }
  108.     }
  109.       break;
  110.     case 6: /* Hid Obj*/
  111.       (void) delete_object(y, x);
  112.       place_object(y, x);
  113.       msg_print("Hmmm, there was something under this rock.");
  114.       break;
  115.     case 7:  /* STR Dart*/
  116.       if (test_hit(125, 0, 0, p_ptr->pac+p_ptr->ptoac, CLA_MISC_HIT))
  117.     {
  118.       if (!py.flags.sustain_str)
  119.         {
  120.           (void) dec_stat(A_STR);
  121.           objdes(tmp, t_ptr, TRUE);
  122.           take_hit(dam, tmp);
  123.           msg_print("A small dart weakens you!");
  124.         }
  125.       else
  126.         msg_print("A small dart hits you.");
  127.     }
  128.       else
  129.     msg_print("A small dart barely misses you.");
  130.       break;
  131.     case 8: /* Teleport*/
  132.       teleport_flag = TRUE;
  133.       msg_print("You hit a teleport trap!");
  134.       /* Light up the teleport trap, before we teleport away.  */
  135.       move_light (y, x, y, x);
  136.       break;
  137.     case 9: /* Rockfall*/
  138.       take_hit(dam, "a falling rock");
  139.       (void) delete_object(y, x);
  140.       place_rubble(y, x);
  141.       msg_print("You are hit by falling rock.");
  142.       break;
  143.     case 10: /* Corrode gas*/
  144.       /* Makes more sense to print the message first, then damage an
  145.      object.  */
  146.       msg_print("A strange red gas surrounds you.");
  147.       corrode_gas("corrosion gas");
  148.       break;
  149.     case 11: /* Summon mon*/
  150.       (void) delete_object(y, x);    /* Rune disappears.    */
  151.       num = 2 + randint (3);
  152.       for (i = 0; i < num; i++)
  153.     {
  154.       ty = y;
  155.       tx = x;
  156.       (void) summon_monster(&ty, &tx, FALSE);
  157.     }
  158.       break;
  159.     case 12: /* Fire trap*/
  160.       msg_print("You are enveloped in flames!");
  161.       fire_dam(dam, "a fire trap");
  162.       break;
  163.     case 13: /* Acid trap*/
  164.       msg_print("You are splashed with acid!");
  165.       acid_dam(dam, "an acid trap");
  166.       break;
  167.     case 14: /* Poison gas*/
  168.       msg_print("A pungent green gas surrounds you!");
  169.       poison_gas(dam, "a poison gas trap");
  170.       break;
  171.     case 15: /* Blind Gas */
  172.       msg_print("A black gas surrounds you!");
  173.       py.flags.blind += randint(50) + 50;
  174.       break;
  175.     case 16: /* Confuse Gas*/
  176.       msg_print("A gas of scintillating colors surrounds you!");
  177.       py.flags.confused += randint(15) + 15;
  178.       break;
  179.     case 17: /* Slow Dart*/
  180.       if (test_hit(125, 0, 0, p_ptr->pac+p_ptr->ptoac, CLA_MISC_HIT))
  181.     {
  182.       objdes(tmp, t_ptr, TRUE);
  183.       take_hit(dam, tmp);
  184.       msg_print("A small dart hits you!");
  185.       if (py.flags.free_act)
  186.         msg_print("You are unaffected.");
  187.       else
  188.         py.flags.slow += randint(20) + 10;
  189.     }
  190.       else
  191.     msg_print("A small dart barely misses you.");
  192.       break;
  193.     case 18: /* CON Dart*/
  194.       if (test_hit(125, 0, 0, p_ptr->pac+p_ptr->ptoac, CLA_MISC_HIT))
  195.     {
  196.       if (!py.flags.sustain_con)
  197.         {
  198.           (void) dec_stat(A_CON);
  199.           objdes(tmp, t_ptr, TRUE);
  200.           take_hit(dam, tmp);
  201.           msg_print("A small dart saps your health!");
  202.         }
  203.       else
  204.         msg_print("A small dart hits you.");
  205.     }
  206.       else
  207.     msg_print("A small dart barely misses you.");
  208.       break;
  209.     case 19: /*Secret Door*/
  210.       break;
  211.     case 99: /* Scare Mon*/
  212.       break;
  213.  
  214.       /* Town level traps are special,    the stores.    */
  215.     case 101: /* General    */
  216.       enter_store(0);
  217.       break;
  218.     case 102: /* Armory        */
  219.       enter_store(1);
  220.       break;
  221.     case 103: /* Weaponsmith*/
  222.       enter_store(2);
  223.       break;
  224.     case 104: /* Temple        */
  225.       enter_store(3);
  226.       break;
  227.     case 105: /* Alchemy    */
  228.       enter_store(4);
  229.       break;
  230.     case 106: /* Magic-User */
  231.       enter_store(5);
  232.       break;
  233.  
  234.     default:
  235.       msg_print("Unknown trap value.");
  236.       break;
  237.     }
  238. }
  239.  
  240.  
  241. /* Return spell number and failure chance        -RAK-    */
  242. /* returns -1 if no spells in book
  243.    returns 1 if choose a spell in book to cast
  244.    returns 0 if don't choose a spell, i.e. exit with an escape */
  245. int cast_spell(prompt, item_val, sn, sc)
  246. char *prompt;
  247. int item_val;
  248. int *sn, *sc;
  249. {
  250.   int32u j;
  251.   register int i, k;
  252.   int spell[31], result, first_spell;
  253.   register spell_type *s_ptr;
  254.  
  255.   result = -1;
  256.   i = 0;
  257.   j = inventory[item_val].flags;
  258.   first_spell = bit_pos(&j);
  259.   /* set j again, since bit_pos modified it */
  260.   j = inventory[item_val].flags & spell_learned;
  261.   s_ptr = magic_spell[py.misc.pclass-1];
  262.   while (j)
  263.     {
  264.       k = bit_pos(&j);
  265.       if (s_ptr[k].slevel <= py.misc.lev)
  266.     {
  267.       spell[i] = k;
  268.       i++;
  269.     }
  270.     }
  271.   if (i > 0)
  272.     {
  273.       result = get_spell(spell, i, sn, sc, prompt, first_spell);
  274.       if (result && magic_spell[py.misc.pclass-1][*sn].smana > py.misc.cmana)
  275.     {
  276.       if (class[py.misc.pclass].spell == MAGE)
  277.         result = get_check("You summon your limited strength to cast \
  278. this one! Confirm?");
  279.       else
  280.         result = get_check("The gods may think you presumptuous for \
  281. this! Confirm?");
  282.     }
  283.     }
  284.   return(result);
  285. }
  286.  
  287.  
  288. /* Player is on an object.  Many things can happen based -RAK-    */
  289. /* on the TVAL of the object.  Traps are set off, money and most */
  290. /* objects are picked up.  Some objects, such as open doors, just*/
  291. /* sit there.                               */
  292. static void carry(y, x, pickup)
  293. int y, x;
  294. int pickup;
  295. {
  296.   register int locn, i;
  297.   bigvtype out_val, tmp_str;
  298.   register cave_type *c_ptr;
  299.   register inven_type *i_ptr;
  300.  
  301.   c_ptr = &cave[y][x];
  302.   i_ptr = &t_list[c_ptr->tptr];
  303.   i = t_list[c_ptr->tptr].tval;
  304.   if (i <= TV_MAX_PICK_UP)
  305.     {
  306.       end_find();
  307.       /* There's GOLD in them thar hills!      */
  308.       if (i == TV_GOLD)
  309.     {
  310.       py.misc.au += i_ptr->cost;
  311.       objdes(tmp_str, i_ptr, TRUE);
  312.       (void) sprintf(out_val,
  313.              "You have found %ld gold pieces worth of %s",
  314.              i_ptr->cost, tmp_str);
  315.       prt_gold();
  316.       (void) delete_object(y, x);
  317.       msg_print(out_val);
  318.     }
  319.       else
  320.     {
  321.       if (inven_check_num(i_ptr))       /* Too many objects?        */
  322.         {                /* Okay,  pick it up      */
  323.           if (pickup && prompt_carry_flag)
  324.         {
  325.           objdes(tmp_str, i_ptr, TRUE);
  326.           /* change the period to a question mark */
  327.           tmp_str[strlen(tmp_str)-1] = '?';
  328.           (void) sprintf(out_val, "Pick up %s", tmp_str);
  329.           pickup = get_check(out_val);
  330.         }
  331.           /* Check to see if it will change the players speed. */
  332.           if (pickup && !inven_check_weight(i_ptr))
  333.         {
  334.           objdes(tmp_str, i_ptr, TRUE);
  335.           /* change the period to a question mark */
  336.           tmp_str[strlen(tmp_str)-1] = '?';
  337.           (void) sprintf(out_val,
  338.                  "Exceed your weight limit to pick up %s",
  339.                  tmp_str);
  340.           pickup = get_check(out_val);
  341.         }
  342.           /* Attempt to pick up an object.           */
  343.           if (pickup)
  344.         {
  345.           locn = inven_carry(i_ptr);
  346.           objdes(tmp_str, &inventory[locn], TRUE);
  347.           (void) sprintf(out_val, "You have %s (%c)",tmp_str,locn+'a');
  348.           msg_print(out_val);
  349.           (void) delete_object(y, x);
  350.         }
  351.         }
  352.       else
  353.         {
  354.           objdes(tmp_str, i_ptr, TRUE);
  355.           (void) sprintf(out_val, "You can't carry %s", tmp_str);
  356.           msg_print(out_val);
  357.         }
  358.     }
  359.     }
  360.   /* OPPS!                   */
  361.   else if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP || i == TV_STORE_DOOR)
  362.     hit_trap(y, x);
  363. }
  364.  
  365.  
  366. /* Deletes a monster entry from the level        -RAK-    */
  367. void delete_monster(j)
  368. int j;
  369. {
  370.   register monster_type *m_ptr;
  371.  
  372.   m_ptr = &m_list[j];
  373.   cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  374.   if (m_ptr->ml)
  375.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  376.   if (j != mfptr - 1)
  377.     {
  378.       m_ptr = &m_list[mfptr - 1];
  379.       cave[m_ptr->fy][m_ptr->fx].cptr = j;
  380.       m_list[j] = m_list[mfptr - 1];
  381.     }
  382.   mfptr--;
  383.   m_list[mfptr] = blank_monster;
  384.   if (mon_tot_mult > 0)
  385.     mon_tot_mult--;
  386. }
  387.  
  388. /* The following two procedures implement the same function as delete monster.
  389.    However, they are used within creatures(), because deleting a monster
  390.    while scanning the m_list causes two problems, monsters might get two
  391.    turns, and m_ptr/monptr might be invalid after the delete_monster.
  392.    Hence the delete is done in two steps. */
  393. /* fix1_delete_monster does everything delete_monster does except delete
  394.    the monster record and reduce mfptr, this is called in breathe, and
  395.    a couple of places in creatures.c */
  396. void fix1_delete_monster(j)
  397. int j;
  398. {
  399.   register monster_type *m_ptr;
  400.  
  401.   m_ptr = &m_list[j];
  402.   /* force the hp negative to ensure that the monster is dead, for example,
  403.      if the monster was just eaten by another, it will still have positive
  404.      hit points */
  405.   m_ptr->hp = -1;
  406.   cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  407.   if (m_ptr->ml)
  408.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  409.   if (mon_tot_mult > 0)
  410.     mon_tot_mult--;
  411. }
  412.  
  413. /* fix2_delete_monster does everything in delete_monster that wasn't done
  414.    by fix1_monster_delete above, this is only called in creatures() */
  415. void fix2_delete_monster(j)
  416. int j;
  417. {
  418.   register monster_type *m_ptr;
  419.  
  420.   if (j != mfptr - 1)
  421.     {
  422.       m_ptr = &m_list[mfptr - 1];
  423.       cave[m_ptr->fy][m_ptr->fx].cptr = j;
  424.       m_list[j] = m_list[mfptr - 1];
  425.     }
  426.   m_list[mfptr - 1] = blank_monster;
  427.   mfptr--;
  428. }
  429.  
  430.  
  431. /* Creates objects nearby the coordinates given        -RAK-      */
  432. static int summon_object(y, x, num, typ)
  433. int y, x, num, typ;
  434. {
  435.   register int i, j, k;
  436.   register cave_type *c_ptr;
  437.   int real_typ, res;
  438.  
  439.   if (typ == 1)
  440.     real_typ = 1; /* typ == 1 -> objects */
  441.   else
  442.     real_typ = 256; /* typ == 2 -> gold */
  443.   res = 0;
  444.   do
  445.     {
  446.       i = 0;
  447.       do
  448.     {
  449.       j = y - 3 + randint(5);
  450.       k = x - 3 + randint(5);
  451.       if (in_bounds(j, k) && los(y, x, j, k))
  452.         {
  453.           c_ptr = &cave[j][k];
  454.           if (c_ptr->fval <= MAX_OPEN_SPACE && (c_ptr->tptr == 0))
  455.         {
  456.           if (typ == 3) /* typ == 3 -> 50% objects, 50% gold */
  457.             {
  458.               if (randint(100) < 50)
  459.             real_typ = 1;
  460.               else
  461.             real_typ = 256;
  462.             }
  463.           if (real_typ == 1)
  464.             place_object(j, k);
  465.           else
  466.             place_gold(j, k);
  467.           lite_spot(j, k);
  468.           if (test_light(j, k))
  469.             res += real_typ;
  470.           i = 20;
  471.         }
  472.         }
  473.       i++;
  474.     }
  475.       while (i <= 20);
  476.       num--;
  477.     }
  478.   while (num != 0);
  479.   return res;
  480. }
  481.  
  482.  
  483. /* Deletes object from given location            -RAK-    */
  484. int delete_object(y, x)
  485. int y, x;
  486. {
  487.   register int delete;
  488.   register cave_type *c_ptr;
  489.  
  490.   c_ptr = &cave[y][x];
  491.   if (c_ptr->fval == BLOCKED_FLOOR)
  492.     c_ptr->fval = CORR_FLOOR;
  493.   pusht(c_ptr->tptr);
  494.   c_ptr->tptr = 0;
  495.   c_ptr->fm = FALSE;
  496.   lite_spot(y, x);
  497.   if (test_light(y, x))
  498.     delete = TRUE;
  499.   else
  500.     delete = FALSE;
  501.   return(delete);
  502. }
  503.  
  504.  
  505. /* Allocates objects upon a creatures death        -RAK-    */
  506. /* Oh well,  another creature bites the dust.  Reward the victor*/
  507. /* based on flags set in the main creature record         */
  508. /* Returns a mask of bits from the given flags which indicates what the
  509.    monster is seen to have dropped.  This may be added to monster memory. */
  510. int32u monster_death(y, x, flags)
  511. int y, x;
  512. register int32u flags;
  513. {
  514.   register int i, number;
  515.   int32u dump, res;
  516. #if defined(ATARIST_MWC)
  517.   int32u holder;    /* avoid a compiler bug */
  518. #endif
  519.  
  520. #if !defined(ATARIST_MWC)
  521.   if (flags & CM_CARRY_OBJ)
  522.     i = 1;
  523.   else
  524.     i = 0;
  525.   if (flags & CM_CARRY_GOLD)
  526.     i += 2;
  527.  
  528.   number = 0;
  529.   if ((flags & CM_60_RANDOM) && (randint(100) < 60))
  530.     number++;
  531.   if ((flags & CM_90_RANDOM) && (randint(100) < 90))
  532.     number++;
  533.   if (flags & CM_1D2_OBJ)
  534.     number += randint(2);
  535.   if (flags & CM_2D2_OBJ)
  536.     number += damroll(2, 2);
  537.   if (flags & CM_4D2_OBJ)
  538.     number += damroll(4, 2);
  539.   if (number > 0)
  540.     dump = summon_object(y, x, number, i);
  541.   else
  542.     dump = 0;
  543. #else
  544.   holder = CM_CARRY_OBJ;
  545.   if (flags & holder)
  546.     i = 1;
  547.   else
  548.     i = 0;
  549.   holder = CM_CARRY_GOLD;
  550.   if (flags & holder)
  551.     i += 2;
  552.  
  553.   number = 0;
  554.   holder = CM_60_RANDOM;
  555.   if ((flags & holder) && (randint(100) < 60))
  556.     number++;
  557.   holder = CM_90_RANDOM;
  558.   if ((flags & holder) && (randint(100) < 90))
  559.     number++;
  560.   holder = CM_1D2_OBJ;
  561.   if (flags & holder)
  562.     number += randint(2);
  563.   holder = CM_2D2_OBJ;
  564.   if (flags & holder)
  565.     number += damroll(2, 2);
  566.   holder = CM_4D2_OBJ;
  567.   if (flags & holder)
  568.     number += damroll(4, 2);
  569.   if (number > 0)
  570.     dump = summon_object(y, x, number, i);
  571.   else
  572.     dump = 0;
  573.  
  574.  
  575. #endif
  576.  
  577. #if defined(ATARIST_MWC)
  578.   holder = CM_WIN;
  579.   if (flags & holder)
  580. #else
  581.   if (flags & CM_WIN)
  582. #endif
  583.     {
  584.       total_winner = TRUE;
  585.       prt_winner();
  586.       msg_print("*** CONGRATULATIONS *** You have won the game.");
  587.       msg_print("You cannot save this game, but you may retire when ready.");
  588.     }
  589.  
  590.   if (dump)
  591.     {
  592.       res = 0;
  593.       if (dump & 255)
  594. #ifdef ATARIST_MWC
  595.     {
  596.       holder = CM_CARRY_OBJ;
  597.       res |= holder;
  598.     }
  599. #else
  600.         res |= CM_CARRY_OBJ;
  601. #endif
  602.       if (dump >= 256)
  603. #ifdef ATARIST_MWC
  604.     {
  605.       holder = CM_CARRY_GOLD;
  606.       res |= holder;
  607.     }
  608. #else
  609.     res |= CM_CARRY_GOLD;
  610. #endif
  611.       dump = (dump % 256) + (dump / 256);  /* number of items */
  612.       res |= dump << CM_TR_SHIFT;
  613.     }
  614.   else
  615.     res = 0;
  616.  
  617.   return res;
  618. }
  619.  
  620.  
  621. /* Decreases monsters hit points and deletes monster if needed.    */
  622. /* (Picking on my babies.)                   -RAK-   */
  623. int mon_take_hit(monptr, dam)
  624. int monptr, dam;
  625. {
  626.   register int32u i;
  627.   int32 new_exp, new_exp_frac;
  628.   register monster_type *m_ptr;
  629.   register struct misc *p_ptr;
  630.   register creature_type *c_ptr;
  631.   int m_take_hit;
  632.   int32u tmp;
  633. #ifdef ATARIST_MWC
  634.   int32u holder;
  635. #endif
  636.  
  637.   m_ptr = &m_list[monptr];
  638.   m_ptr->hp -= dam;
  639.   m_ptr->csleep = 0;
  640.   if (m_ptr->hp < 0)
  641.     {
  642.       i = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
  643.             c_list[m_ptr->mptr].cmove);
  644.       if ((py.flags.blind < 1 && m_ptr->ml)
  645. #ifdef ATARIST_MWC
  646.       || (c_list[m_ptr->mptr].cmove & (holder = CM_WIN)))
  647. #else
  648.       || (c_list[m_ptr->mptr].cmove & CM_WIN))
  649. #endif
  650.     {
  651. #ifdef ATARIST_MWC
  652.       holder = CM_TREASURE;
  653.       tmp = (c_recall[m_ptr->mptr].r_cmove & holder) >> CM_TR_SHIFT;
  654.       if (tmp > ((i & holder) >> CM_TR_SHIFT))
  655.         i = (i & ~holder) | (tmp << CM_TR_SHIFT);
  656.       c_recall[m_ptr->mptr].r_cmove =
  657.         (c_recall[m_ptr->mptr].r_cmove & ~holder) | i;
  658. #else
  659.       tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE) >> CM_TR_SHIFT;
  660.       if (tmp > ((i & CM_TREASURE) >> CM_TR_SHIFT))
  661.         i = (i & ~CM_TREASURE) | (tmp << CM_TR_SHIFT);
  662.       c_recall[m_ptr->mptr].r_cmove =
  663.         (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE) | i;
  664. #endif
  665.       if (c_recall[m_ptr->mptr].r_kills < MAX_SHORT)
  666.         c_recall[m_ptr->mptr].r_kills++;
  667.     }
  668.       c_ptr = &c_list[m_ptr->mptr];
  669.       p_ptr = &py.misc;
  670.  
  671.       new_exp = ((long)c_ptr->mexp * c_ptr->level) / p_ptr->lev;
  672.       new_exp_frac = ((((long)c_ptr->mexp * c_ptr->level) % p_ptr->lev)
  673.     * 0x10000L / p_ptr->lev) + p_ptr->exp_frac;
  674.       if (new_exp_frac >= 0x10000L)
  675.     {
  676.       new_exp++;
  677.       p_ptr->exp_frac = new_exp_frac - 0x10000L;
  678.     }
  679.       else
  680.     p_ptr->exp_frac = new_exp_frac;
  681.  
  682.       p_ptr->exp += new_exp;
  683.       /* can't call prt_experience() here, as that would result in "new level"
  684.      message appearing before "monster dies" message */
  685.       m_take_hit = m_ptr->mptr;
  686.       /* in case this is called from within creatures(), this is a
  687.      horrible hack, the m_list/creatures() code needs to be
  688.      rewritten */
  689.       if (hack_monptr < monptr)
  690.     delete_monster(monptr);
  691.       else
  692.     fix1_delete_monster(monptr);
  693.     }
  694.   else
  695.     m_take_hit = -1;
  696.   return(m_take_hit);
  697. }
  698.  
  699.  
  700. /* Player attacks a (poor, defenseless) creature    -RAK-    */
  701. void py_attack(y, x)
  702. int y, x;
  703. {
  704.   register int k, blows;
  705.   int crptr, monptr, tot_tohit, base_tohit;
  706.   vtype m_name, out_val;
  707.   register inven_type *i_ptr;
  708.   register struct misc *p_ptr;
  709. #ifdef ATARIST_MWC
  710.   int32u holder;
  711. #endif
  712.  
  713.   crptr = cave[y][x].cptr;
  714.   monptr = m_list[crptr].mptr;
  715.   m_list[crptr].csleep = 0;
  716.   i_ptr = &inventory[INVEN_WIELD];
  717.   /* Does the player know what he's fighting?       */
  718.   if (!m_list[crptr].ml)
  719.     (void) strcpy(m_name, "it");
  720.   else
  721.     (void) sprintf(m_name, "the %s", c_list[monptr].name);
  722.   if (i_ptr->tval != TV_NOTHING)        /* Proper weapon */
  723.     blows = attack_blows((int)i_ptr->weight, &tot_tohit);
  724.   else                      /* Bare hands?   */
  725.     {
  726.       blows = 2;
  727.       tot_tohit = -3;
  728.     }
  729.   if ((i_ptr->tval >= TV_SLING_AMMO) && (i_ptr->tval <= TV_SPIKE))
  730.     /* Fix for arrows */
  731.     blows = 1;
  732.   p_ptr = &py.misc;
  733.   tot_tohit += p_ptr->ptohit;
  734.   /* if creature not lit, make it more difficult to hit */
  735.   if (m_list[crptr].ml)
  736.     base_tohit = p_ptr->bth;
  737.   else
  738.     base_tohit = (p_ptr->bth / 2) - (tot_tohit * (BTH_PLUS_ADJ-1))
  739.       - (p_ptr->lev * class_level_adj[p_ptr->pclass][CLA_BTH] / 2);
  740.  
  741.   /* Loop for number of blows,    trying to hit the critter.      */
  742.   do
  743.     {
  744.       if (test_hit(base_tohit, (int)p_ptr->lev, tot_tohit,
  745.            (int)c_list[monptr].ac, CLA_BTH))
  746.     {
  747.       (void) sprintf(out_val, "You hit %s.", m_name);
  748.       msg_print(out_val);
  749.       if (i_ptr->tval != TV_NOTHING)
  750.         {
  751.           k = pdamroll(i_ptr->damage);
  752.           k = tot_dam(i_ptr, k, monptr);
  753.           k = critical_blow((int)i_ptr->weight, tot_tohit, k, CLA_BTH);
  754.         }
  755.       else                  /* Bare hands!?  */
  756.         {
  757.           k = damroll(1, 1);
  758.           k = critical_blow(1, 0, k, CLA_BTH);
  759.         }
  760.       k += p_ptr->ptodam;
  761.       if (k < 0)  k = 0;
  762.  
  763.       if (py.flags.confuse_monster)
  764.         {
  765.           py.flags.confuse_monster = FALSE;
  766.           msg_print("Your hands stop glowing.");
  767.           if ((c_list[monptr].cdefense & CD_NO_SLEEP)
  768.           || (randint(MAX_MONS_LEVEL) < c_list[monptr].level))
  769.         (void) sprintf(out_val, "%s is unaffected.", m_name);
  770.           else
  771.         {
  772.           (void) sprintf(out_val, "%s appears confused.", m_name);
  773.           m_list[crptr].confused = TRUE;
  774.         }
  775.           msg_print(out_val);
  776.           if (m_list[crptr].ml && randint(4) == 1)
  777.         c_recall[monptr].r_cdefense |=
  778.           c_list[monptr].cdefense & CD_NO_SLEEP;
  779.         }
  780.  
  781.       /* See if we done it in.                 */
  782.       if (mon_take_hit(crptr, k) >= 0)
  783.         {
  784.           (void) sprintf(out_val, "You have slain %s.", m_name);
  785.           msg_print(out_val);
  786.           prt_experience();
  787.           blows = 0;
  788.         }
  789.  
  790.       if ((i_ptr->tval >= TV_SLING_AMMO)
  791.           && (i_ptr->tval <= TV_SPIKE)) /* Use missiles up*/
  792.         {
  793.           i_ptr->number--;
  794.           inven_weight -= i_ptr->weight;
  795. #ifdef ATARIST_MWC
  796.           py.flags.status |= (holder = PY_STR_WGT);
  797. #else
  798.           py.flags.status |= PY_STR_WGT;
  799. #endif
  800.           if (i_ptr->number == 0)
  801.         {
  802.           equip_ctr--;
  803.           py_bonuses(i_ptr, -1);
  804.           invcopy(i_ptr, OBJ_NOTHING);
  805.           calc_bonuses();
  806.         }
  807.         }
  808.     }
  809.       else
  810.     {
  811.       (void) sprintf(out_val, "You miss %s.", m_name);
  812.       msg_print(out_val);
  813.     }
  814.       blows--;
  815.     }
  816.   while (blows >= 1);
  817. }
  818.  
  819.  
  820. /* Moves player from one space to another.        -RAK-    */
  821. /* Note: This routine has been pre-declared; see that for argument*/
  822. void move_char(dir, do_pickup)
  823. int dir, do_pickup;
  824. {
  825.   int old_row, old_col, old_find_flag;
  826.   int y, x;
  827.   register int i, j;
  828.   register cave_type *c_ptr, *d_ptr;
  829.  
  830.   if ((py.flags.confused > 0) &&    /* Confused?         */
  831.       (randint(4) > 1) &&        /* 75% random movement   */
  832.       (dir != 5))            /* Never random if sitting*/
  833.     {
  834.       dir = randint(9);
  835.       end_find();
  836.     }
  837.   y = char_row;
  838.   x = char_col;
  839.   if (mmove(dir, &y, &x))    /* Legal move?          */
  840.     {
  841.       c_ptr = &cave[y][x];
  842.       /* if there is no creature, or an unlit creature in the walls then... */
  843.       /* disallow attacks against unlit creatures in walls because moving into
  844.      a wall is a free turn normally, hence don't give player free turns
  845.      attacking each wall in an attempt to locate the invisible creature,
  846.      instead force player to tunnel into walls which always takes a turn */
  847.       if ((c_ptr->cptr < 2)
  848.       || (!m_list[c_ptr->cptr].ml && c_ptr->fval >= MIN_CLOSED_SPACE))
  849.     {
  850.       if (c_ptr->fval <= MAX_OPEN_SPACE) /* Open floor spot    */
  851.         {
  852.           /* Make final assignments of char co-ords */
  853.           old_row = char_row;
  854.           old_col = char_col;
  855.           char_row = y;
  856.           char_col = x;
  857.           /* Move character record (-1)           */
  858.           move_rec(old_row, old_col, char_row, char_col);
  859.           /* Check for new panel               */
  860.           if (get_panel(char_row, char_col, FALSE))
  861.         prt_map();
  862.           /* Check to see if he should stop           */
  863.           if (find_flag)
  864.         area_affect(dir, char_row, char_col);
  865.           /* Check to see if he notices something  */
  866.           /* fos may be negative if have good rings of searching */
  867.           if ((py.misc.fos <= 1) || (randint(py.misc.fos) == 1) ||
  868.           (py.flags.status & PY_SEARCH))
  869.         search(char_row, char_col, py.misc.srh);
  870.           /* A room of light should be lit.         */
  871.           if (c_ptr->fval == LIGHT_FLOOR)
  872.         {
  873.           if (!c_ptr->pl && !py.flags.blind)
  874.             light_room(char_row, char_col);
  875.         }
  876.           /* In doorway of light-room?           */
  877.           else if (c_ptr->lr && (py.flags.blind < 1))
  878.         for (i = (char_row - 1); i <= (char_row + 1); i++)
  879.           for (j = (char_col - 1); j <= (char_col + 1); j++)
  880.             {
  881.               d_ptr = &cave[i][j];
  882.               if ((d_ptr->fval == LIGHT_FLOOR) && (!d_ptr->pl))
  883.             light_room(i, j);
  884.             }
  885.           /* Move the light source               */
  886.           move_light(old_row, old_col, char_row, char_col);
  887.           /* An object is beneath him.         */
  888.           if (c_ptr->tptr != 0)
  889.         {
  890.           carry(char_row, char_col, do_pickup);
  891.           /* if stepped on falling rock trap, and space contains
  892.              rubble, then step back into a clear area */
  893.           if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
  894.             {
  895.               move_rec(char_row, char_col, old_row, old_col);
  896.               move_light(char_row, char_col, old_row, old_col);
  897.               char_row = old_row;
  898.               char_col = old_col;
  899.               /* check to see if we have stepped back onto another
  900.              trap, if so, set it off */
  901.               c_ptr = &cave[char_row][char_col];
  902.               if (c_ptr->tptr != 0)
  903.             {
  904.               i = t_list[c_ptr->tptr].tval;
  905.               if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP
  906.                   || i == TV_STORE_DOOR)
  907.                 hit_trap(char_row, char_col);
  908.             }
  909.             }
  910.         }
  911.         }
  912.       else      /*Can't move onto floor space*/
  913.         {
  914.           if (!find_flag && (c_ptr->tptr != 0))
  915.         {
  916.           if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
  917.             msg_print("There is rubble blocking your way.");
  918.           else if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR)
  919.             msg_print("There is a closed door blocking your way.");
  920.         }
  921.           else
  922.         end_find();
  923.           free_turn_flag = TRUE;
  924.         }
  925.     }
  926.       else      /* Attacking a creature! */
  927.     {
  928.       old_find_flag = find_flag;
  929.       end_find();
  930.       /* if player can see monster, and was in find mode, then nothing */
  931.       if (m_list[c_ptr->cptr].ml && old_find_flag)
  932.         {
  933.           /* did not do anything this turn */
  934.           free_turn_flag = TRUE;
  935.         }
  936.       else
  937.         {
  938.           if (py.flags.afraid < 1)        /* Coward?    */
  939.         py_attack(y, x);
  940.           else                /* Coward!    */
  941.         msg_print("You are too afraid!");
  942.         }
  943.     }
  944.     }
  945. }
  946.  
  947.  
  948. /* Chests have traps too.                -RAK-    */
  949. /* Note: Chest traps are based on the FLAGS value         */
  950. void chest_trap(y, x)
  951. int y, x;
  952. {
  953.   register int i;
  954.   int j, k;
  955.   register inven_type *t_ptr;
  956.  
  957.   t_ptr = &t_list[cave[y][x].tptr];
  958.   if (CH_LOSE_STR & t_ptr->flags)
  959.     {
  960.       msg_print("A small needle has pricked you!");
  961.       if (!py.flags.sustain_str)
  962.     {
  963.       (void) dec_stat(A_STR);
  964.       take_hit(damroll(1, 4), "a poison needle");
  965.       msg_print("You feel weakened!");
  966.     }
  967.       else
  968.     msg_print("You are unaffected.");
  969.     }
  970.   if (CH_POISON & t_ptr->flags)
  971.     {
  972.       msg_print("A small needle has pricked you!");
  973.       take_hit(damroll(1, 6), "a poison needle");
  974.       py.flags.poisoned += 10 + randint(20);
  975.     }
  976.   if (CH_PARALYSED & t_ptr->flags)
  977.     {
  978.       msg_print("A puff of yellow gas surrounds you!");
  979.       if (py.flags.free_act)
  980.     msg_print("You are unaffected.");
  981.       else
  982.     {
  983.       msg_print("You choke and pass out.");
  984.       py.flags.paralysis = 10 + randint(20);
  985.     }
  986.     }
  987.   if (CH_SUMMON & t_ptr->flags)
  988.     {
  989.       for (i = 0; i < 3; i++)
  990.     {
  991.       j = y;
  992.       k = x;
  993.       (void) summon_monster(&j, &k, FALSE);
  994.     }
  995.     }
  996.   if (CH_EXPLODE & t_ptr->flags)
  997.     {
  998.       msg_print("There is a sudden explosion!");
  999.       (void) delete_object(y, x);
  1000.       take_hit(damroll(5, 8), "an exploding chest");
  1001.     }
  1002. }
  1003.  
  1004.  
  1005. /* Opens a closed door or closed chest.        -RAK-    */
  1006. void openobject()
  1007. {
  1008.   int y, x, i, dir;
  1009.   int flag, no_object;
  1010.   register cave_type *c_ptr;
  1011.   register inven_type *t_ptr;
  1012.   register struct misc *p_ptr;
  1013.   register monster_type *m_ptr;
  1014.   vtype m_name, out_val;
  1015. #ifdef ATARIST_MWC
  1016.   int32u holder;
  1017. #endif
  1018.  
  1019.   y = char_row;
  1020.   x = char_col;
  1021.   if (get_dir(CNIL, &dir))
  1022.     {
  1023.       (void) mmove(dir, &y, &x);
  1024.       c_ptr = &cave[y][x];
  1025.       no_object = FALSE;
  1026.       if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  1027.       (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR
  1028.        || t_list[c_ptr->tptr].tval == TV_CHEST))
  1029.     {
  1030.       m_ptr = &m_list[c_ptr->cptr];
  1031.       if (m_ptr->ml)
  1032.         (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
  1033.       else
  1034.         (void) strcpy (m_name, "Something");
  1035.       (void) sprintf(out_val, "%s is in your way!", m_name);
  1036.       msg_print(out_val);
  1037.     }
  1038.       else if (c_ptr->tptr != 0)
  1039.     /* Closed door         */
  1040.     if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR)
  1041.       {
  1042.         t_ptr = &t_list[c_ptr->tptr];
  1043.         if (t_ptr->p1 > 0)     /* It's locked.    */
  1044.           {
  1045.         p_ptr = &py.misc;
  1046.         i = p_ptr->disarm + 2*todis_adj() + stat_adj(A_INT)
  1047.           + (class_level_adj[p_ptr->pclass][CLA_DISARM]
  1048.              * p_ptr->lev / 3);
  1049.         if (py.flags.confused > 0)
  1050.           msg_print("You are too confused to pick the lock.");
  1051.         else if ((i-t_ptr->p1) > randint(100))
  1052.           {
  1053.             msg_print("You have picked the lock.");
  1054.             py.misc.exp++;
  1055.             prt_experience();
  1056.             t_ptr->p1 = 0;
  1057.           }
  1058.         else
  1059.           count_msg_print("You failed to pick the lock.");
  1060.           }
  1061.         else if (t_ptr->p1 < 0)     /* It's stuck      */
  1062.           msg_print("It appears to be stuck.");
  1063.         if (t_ptr->p1 == 0)
  1064.           {
  1065.         invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  1066.         c_ptr->fval = CORR_FLOOR;
  1067.         lite_spot(y, x);
  1068.         command_count = 0;
  1069.           }
  1070.       }
  1071.       /* Open a closed chest.             */
  1072.     else if (t_list[c_ptr->tptr].tval == TV_CHEST)
  1073.       {
  1074.         p_ptr = &py.misc;
  1075.         i = p_ptr->disarm + 2*todis_adj() + stat_adj(A_INT)
  1076.           + (class_level_adj[p_ptr->pclass][CLA_DISARM] * p_ptr->lev / 3);
  1077.         t_ptr = &t_list[c_ptr->tptr];
  1078.         flag = FALSE;
  1079.         if (CH_LOCKED & t_ptr->flags)
  1080.           if (py.flags.confused > 0)
  1081.         msg_print("You are too confused to pick the lock.");
  1082.           else if ((i-(int)t_ptr->level) > randint(100))
  1083.         {
  1084.           msg_print("You have picked the lock.");
  1085.           flag = TRUE;
  1086.           py.misc.exp += t_ptr->level;
  1087.           prt_experience();
  1088.         }
  1089.           else
  1090.         count_msg_print("You failed to pick the lock.");
  1091.         else
  1092.           flag = TRUE;
  1093.         if (flag)
  1094.           {
  1095.         t_ptr->flags &= ~CH_LOCKED;
  1096.         t_ptr->name2 = SN_EMPTY;
  1097.         known2(t_ptr);
  1098.         t_ptr->cost = 0;
  1099.           }
  1100.         flag = FALSE;
  1101.         /* Was chest still trapped?     (Snicker)   */
  1102.         if ((CH_LOCKED & t_ptr->flags) == 0)
  1103.           {
  1104.         chest_trap(y, x);
  1105.         if (c_ptr->tptr != 0)
  1106.           flag = TRUE;
  1107.           }
  1108.         /* Chest treasure is allocated as if a creature   */
  1109.         /* had been killed.                   */
  1110.         if (flag)
  1111.           {
  1112.         /* clear the cursed chest/monster win flag, so that people
  1113.            can not win by opening a cursed chest */
  1114. #ifdef ATARIST_MWC
  1115.         t_list[c_ptr->tptr].flags &= ~(holder = TR_CURSED);
  1116. #else
  1117.         t_list[c_ptr->tptr].flags &= ~TR_CURSED;
  1118. #endif
  1119.         (void) monster_death(y, x, t_list[c_ptr->tptr].flags);
  1120.         t_list[c_ptr->tptr].flags = 0;
  1121.           }
  1122.       }
  1123.     else
  1124.       no_object = TRUE;
  1125.       else
  1126.     no_object = TRUE;
  1127.  
  1128.       if (no_object)
  1129.     {
  1130.       msg_print("I do not see anything you can open there.");
  1131.       free_turn_flag = TRUE;
  1132.     }
  1133.     }
  1134. }
  1135.  
  1136.  
  1137. /* Closes an open door.                -RAK-    */
  1138. void closeobject()
  1139. {
  1140.   int y, x, dir, no_object;
  1141.   vtype out_val, m_name;
  1142.   register cave_type *c_ptr;
  1143.   register monster_type *m_ptr;
  1144.  
  1145.   y = char_row;
  1146.   x = char_col;
  1147.   if (get_dir(CNIL, &dir))
  1148.     {
  1149.       (void) mmove(dir, &y, &x);
  1150.       c_ptr = &cave[y][x];
  1151.       no_object = FALSE;
  1152.       if (c_ptr->tptr != 0)
  1153.     if (t_list[c_ptr->tptr].tval == TV_OPEN_DOOR)
  1154.       if (c_ptr->cptr == 0)
  1155.         if (t_list[c_ptr->tptr].p1 == 0)
  1156.           {
  1157.         invcopy(&t_list[c_ptr->tptr], OBJ_CLOSED_DOOR);
  1158.         c_ptr->fval = BLOCKED_FLOOR;
  1159.         lite_spot(y, x);
  1160.           }
  1161.         else
  1162.           msg_print("The door appears to be broken.");
  1163.       else
  1164.         {
  1165.           m_ptr = &m_list[c_ptr->cptr];
  1166.           if (m_ptr->ml)
  1167.         (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
  1168.           else
  1169.         (void) strcpy (m_name, "Something");
  1170.           (void) sprintf(out_val, "%s is in your way!", m_name);
  1171.           msg_print(out_val);
  1172.         }
  1173.     else
  1174.       no_object = TRUE;
  1175.       else
  1176.     no_object = TRUE;
  1177.  
  1178.       if (no_object)
  1179.     {
  1180.       msg_print("I do not see anything you can close there.");
  1181.       free_turn_flag = TRUE;
  1182.     }
  1183.     }
  1184. }
  1185.  
  1186.  
  1187. /* Tunneling through real wall: 10, 11, 12        -RAK-    */
  1188. /* Used by TUNNEL and WALL_TO_MUD                 */
  1189. int twall(y, x, t1, t2)
  1190. int y, x, t1, t2;
  1191. {
  1192.   register int i, j;
  1193.   register cave_type *c_ptr;
  1194.   int res, found;
  1195.  
  1196.   res = FALSE;
  1197.   if (t1 > t2)
  1198.     {
  1199.       c_ptr = &cave[y][x];
  1200.       if (c_ptr->lr)
  1201.     {
  1202.       /* should become a room space, check to see whether it should be
  1203.          LIGHT_FLOOR or DARK_FLOOR */
  1204.       found = FALSE;
  1205.       for (i = y-1; i <= y+1; i++)
  1206.         for (j = x-1; j <= x+1; j++)
  1207.           if (cave[i][j].fval <= MAX_CAVE_ROOM)
  1208.         {
  1209.           c_ptr->fval = cave[i][j].fval;
  1210.           c_ptr->pl = cave[i][j].pl;
  1211.           found = TRUE;
  1212.           break;
  1213.         }
  1214.       if (!found)
  1215.         {
  1216.           c_ptr->fval = CORR_FLOOR;
  1217.           c_ptr->pl = FALSE;
  1218.         }
  1219.     }
  1220.       else
  1221.     {
  1222.       /* should become a corridor space */
  1223.       c_ptr->fval  = CORR_FLOOR;
  1224.       c_ptr->pl = FALSE;
  1225.     }
  1226.       c_ptr->fm = FALSE;
  1227.       if (panel_contains(y, x))
  1228.     if ((c_ptr->tl || c_ptr->pl) && c_ptr->tptr != 0)
  1229.       msg_print("You have found something!");
  1230.       lite_spot(y, x);
  1231.       res = TRUE;
  1232.     }
  1233.   return(res);
  1234. }
  1235.